package cn.com.cennavi.service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

/**
 * 高精度分车道路况，路况合并
 * 
 * @ClassName: LaneSpeedSplitCombine
 * @Description: TODO（这里用一句话描述这个类的作用）
 * @author bull
 * @date 2016年3月8日 下午1:04:32
 *
 */
public class LaneSpeedSplitCombine {
	/**
	 * 速度聚类算法
	 */
	public ArrayList<String> getClassPattern(String line, int uniformSpeedContinueLength, int uniformSpeedRrror, float errorRatio) {

		/** 找匀速区间小段,输出规格：[5_42:50.0, 43_85:56.0, 86_176:62.0, 177_288:56.0] **/
		ArrayList<String> uniformspeedAreaList = getUniformspeedAreaList(line, uniformSpeedContinueLength, uniformSpeedRrror);

		/** 根据匀速区间左右扩展,获取扩展后的速度区间，输出规格：0_12:50.0:0_41 **/
		ArrayList<String> extendUniformspeedAreaList = getExtendUniformspeedAreaList(line, uniformspeedAreaList, errorRatio);

		/** 获取每个位置的点属于哪个类 **/
		ArrayList<String> combineUniformspeedAreaList = getCombineUniformspeedAreaList(line, extendUniformspeedAreaList);

		/** 计算交集属于哪个类 **/
		HashMap<String, ArrayList<String>> gpsPointClassList = getGpsPointClassList(line, combineUniformspeedAreaList);

		return getClassDis(line, gpsPointClassList, extendUniformspeedAreaList);

	}

	private static ArrayList<String> getClassDis(String line, HashMap<String, ArrayList<String>> gpsPointClassList, ArrayList<String> extendUniformspeedAreaList) {
		// TODO Auto-generated method stub
		String[] lineArr = line.split("\\|");
		/** 可以作为一类的数据 **/
		TreeMap<Integer, Integer> treeMap = new TreeMap<>();
		for (Map.Entry<String, ArrayList<String>> entry : gpsPointClassList.entrySet()) {
			String className = entry.getKey();
			ArrayList<String> valueList = entry.getValue();
			for (String value : valueList) {
				String[] valueArr = value.split(":");
				String[] arr = className.split("\\_");
				int classNum = arr.length;
				double nowSpeed = Double.parseDouble(value.split(":")[1]);
				double difSpeed = 0;
				if (classNum >= 2) {
					for (int i = 0; i < classNum; i++) {
						String clas = arr[i];
						double speed = Double.parseDouble(extendUniformspeedAreaList.get(Integer.parseInt(clas)).split(":")[1]);
						if (i == 0) {
							difSpeed = Math.abs(speed - nowSpeed);
						} else {
							if (Math.abs(speed - nowSpeed) > difSpeed) {

							} else {

							}
						}
					}
					String[] disArr = valueArr[0].split("\\_");
					int oIndex = Integer.parseInt(disArr[0]);
					int dIndex = Integer.parseInt(disArr[1]);
					for (int m = oIndex; m <= dIndex; m++) {
						treeMap.put(m, dIndex - oIndex + 1);
					}
				} else {
					int oIndex = Integer.parseInt(value.split(":")[0].split("\\_")[0]);
					int dIndex = Integer.parseInt(value.split(":")[0].split("\\_")[1]);
					for (int m = oIndex; m <= dIndex; m++) {
						treeMap.put(m, dIndex - oIndex + 1);
					}
				}
			}

		}
		/** 对分类中较短的数据进行合并 **/
		int oDis = treeMap.firstEntry().getKey();
		int dDis = 0;
		int oLength = treeMap.firstEntry().getValue();
		double totalTime = 0;
		ArrayList<String> outList = new ArrayList<>();
		for (Map.Entry<Integer, Integer> entry : treeMap.entrySet()) {

			int nowDis = entry.getKey();
			int nowLength = entry.getValue();
			double nowSpeed = Double.parseDouble(lineArr[nowDis].split("\\_")[0]);
			double nowTime = (double) 1 / (nowSpeed / 3.6);
			if (nowLength == oLength) {
				totalTime += nowTime;
				dDis = nowDis;
			} else {
				if (nowLength > 10) {
					/** 输出前面的一段 **/
					double averageSpeed = (dDis - oDis + 1) / totalTime * 3.6;
					outList.add(oDis + "_" + dDis + ":" + averageSpeed);
					totalTime = nowTime;
					oDis = nowDis;
					oLength = nowLength;
				} else {
					totalTime += nowTime;
					dDis = nowDis;
				}
			}

		}
		if (dDis - oDis != 0) {
			double averageSpeed = (dDis - oDis + 1) / totalTime * 3.6;
			// if(averageSpeed==0){
			// System.out.println("line==0:"+line);
			// }
			outList.add(oDis + "_" + dDis + ":" + averageSpeed);
		}
		return outList;
	}

	private static HashMap<String, ArrayList<String>> getGpsPointClassList(String line, ArrayList<String> extendUniformspeedAreaList) {
		// TODO Auto-generated method stub
		String[] lineArr = line.split("\\|");
		HashMap<String, ArrayList<String>> dataMap = new HashMap<>();
		TreeMap<Integer, String> dataMp1 = new TreeMap<>();
		int classNum = 0;
		/** 判断第一个自己是不是从0的位置开始的，如果不是开始位置到第一个类的下端算作一段 **/
		int oIndex = 0;
		int dIndex = 0;
		double totalTime = 0;
		String classStr = extendUniformspeedAreaList.get(0);
		for (int j = 0; j < extendUniformspeedAreaList.size(); j++) {
			String nowClass = extendUniformspeedAreaList.get(j);
			if (nowClass.equals(classStr)) {
				double nowTime = 1 / (Double.parseDouble(lineArr[j].split("\\_")[0]) / 3.6);
				totalTime += nowTime;
				dIndex = j;
			} else {
				/** 计算这一段的速度值 **/
				double averageSpeed = (dIndex - oIndex + 1) / totalTime * 3.6;
				String lineStr = oIndex + "_" + dIndex + ":" + averageSpeed + ":" + classStr;
				dataMp1.put(classNum, lineStr);
				classNum++;
				ArrayList<String> arraylist = dataMap.get(classStr);
				if (arraylist == null) {
					ArrayList<String> arraylist1 = new ArrayList<>();
					arraylist1.add(lineStr);
					dataMap.put(classStr, arraylist1);
				} else {
					arraylist.add(lineStr);
				}
				classStr = nowClass;
				oIndex = j;
				double nowTime = 1 / Double.parseDouble(lineArr[j].split("\\_")[0]);
				totalTime = nowTime;
			}
		}
		if (dIndex == extendUniformspeedAreaList.size() - 1) {
			double averageSpeed = (dIndex - oIndex + 1) / totalTime * 3.6;
			String lineStr = oIndex + "_" + dIndex + ":" + averageSpeed + ":" + classStr;
			dataMp1.put(classNum, lineStr);
			classNum++;
			ArrayList<String> arraylist = dataMap.get(classStr);
			if (arraylist == null) {
				ArrayList<String> arraylist1 = new ArrayList<>();
				arraylist1.add(lineStr);
				dataMap.put(classStr, arraylist1);
			} else {
				arraylist.add(lineStr);
			}
		}
		return dataMap;
	}

	/**
	 * 扩展后的处理
	 */
	private static ArrayList<String> getCombineUniformspeedAreaList(String line, ArrayList<String> dataList) {
		// TODO Auto-generated method stub
		ArrayList<String> outdataList = new ArrayList<>();

		String[] lineArr = line.split("\\|");
		int lineSize = lineArr.length;
		for (int i = 0; i < lineSize; i++) {
			int length = i;
			String flag = "";
			for (int j = 0; j < dataList.size(); j++) {
				String str1 = dataList.get(j);
				String[] str1Arr = str1.split("\\:");
				double oDis = Double.parseDouble(str1Arr[2].split("\\_")[0]);
				double dDis = Double.parseDouble(str1Arr[2].split("\\_")[1]);
				/** 如果这个位置属于这个类 **/
				if (length >= oDis && length <= dDis) {
					flag += j + "_";
				}
			}
			if (flag.equals("")) {
				flag = "-1" + "_";
			}
			outdataList.add(flag);
		}
		return outdataList;

	}

	/**
	 * 根据匀速区间左右扩展,获取扩展后的速度区间
	 */
	private static ArrayList<String> getExtendUniformspeedAreaList(String line, ArrayList<String> uniformspeedAreaList, float errorRatio) {
		// TODO Auto-generated method stub
		//[5_42:50.0, 43_85:56.0, 86_176:62.0, 177_288:56.0]
		ArrayList<String> dataist = new ArrayList<>();

		String[] lineArr = line.split("\\|");
		int lineSize = lineArr.length;
		for (int i = 0; i < uniformspeedAreaList.size(); i++) {
			// 27_39:52.0
			String speedInfo = uniformspeedAreaList.get(i);
			String[] strArr = speedInfo.split("\\:");
			String[] oDis_dDis = strArr[0].split("\\_");
			int oDistance = Integer.parseInt(oDis_dDis[0]);
			int dDistance = Integer.parseInt(oDis_dDis[1]);
			double speed = Double.parseDouble(strArr[1]);
			int extandLow = 0;
			int extandUp = 0;
			for (int j = oDistance; j >= 0; j--) {
				if (Math.abs(Double.parseDouble(lineArr[j].split("\\_")[0]) - speed) >= 5) {
					extandLow = j + 1;
					break;
				}
			}

			for (int k = dDistance; k < lineSize; k++) {
				if (Math.abs(Double.parseDouble(lineArr[k].split("\\_")[0]) - speed) >= 5) {
					extandUp = k - 1;
					break;
				}
			}
			if (extandUp == 0) {
				extandUp = lineSize - 1;
			}
			dataist.add(speedInfo + ":" + extandLow + "_" + extandUp);
		}
		/** 合并 **/
		ArrayList<String> outDataList = new ArrayList<>();
		//[5_42:50.0:5_41, 43_85:56.0:22_85, 86_176:62.0:75_175, 177_288:56.0:139_288]
		for (int j = 0; j < dataist.size(); j++) {
			String str1 = dataist.get(j);
			String[] strArr1 = str1.split("\\:");
			double oDis1 = Double.parseDouble(strArr1[2].split("\\_")[0]);
			double dDis1 = Double.parseDouble(strArr1[2].split("\\_")[1]);
			boolean isEnd = false;
			for (int k = 0; k < dataist.size(); k++) {
				String str2 = dataist.get(k);
				String[] strArr2 = str2.split("\\:");
				double oDis2 = Double.parseDouble(strArr2[2].split("\\_")[0]);
				double dDis2 = Double.parseDouble(strArr2[2].split("\\_")[1]);
				/** 被包含 **/
				if (oDis2 <= oDis1 && dDis2 > dDis1) {
					// 该类没有存在的意义了，是别人的儿子
					isEnd = true;
					break;
				}
			}
			if (isEnd == false) {
				/** 輸出 **/
				outDataList.add(str1);

			}
		}
		return outDataList;
	}

	/**
	 * 找匀速区间小段
	 */
	private static ArrayList<String> getUniformspeedAreaList(String line, int uniformSpeedContinueLength, int uniformSpeedRrror) {
		// TODO Auto-generated method stub
		String[] arr = line.split("\\|");
		ArrayList<String> dataist = new ArrayList<>();
		double standSpeed = 0;
		int containedLenght = 0;
		int lowDis = 0;
		int upDis = 0;
		for (int i = 0; i < arr.length; i++) {
			int thisDis = i;
			double nowSpeed = Double.parseDouble(arr[i].split("\\_")[0]);
			if (Math.abs(standSpeed - nowSpeed) <= uniformSpeedRrror) {
				containedLenght++;
				upDis = thisDis;
			} else {
				if (containedLenght >= uniformSpeedContinueLength) {
					String dataLine = lowDis + "_" + upDis + ":" + standSpeed;
					dataist.add(dataLine);
				}
				lowDis = thisDis;
				standSpeed = nowSpeed;
				containedLenght = 0;
			}
		}
		return dataist;
	}
public static void main(String []args){
	String line = "50.0_1|50.0_1|50.0_1|50.0_1|20.0_1|50.0_1|50.0_1|50.0_1|50.0_1|50.0_1|50.0_1|50.0_1|50.0_1|48.0_1|48.0_1|48.0_1|50.0_1|50.0_1|50.0_1|51.0_1|51.0_1|49.0_1|54.0_1|54.0_1|54.0_1|54.0_1|54.0_1|52.0_1|52.0_1|53.0_1|52.0_1|52.0_1|52.0_1|53.0_1|53.0_1|53.0_1|53.0_1|53.0_1|53.0_1|53.0_1|54.0_1|54.0_1|55.0_1|56.0_1|55.0_1|56.0_1|56.0_1|57.0_1|57.0_1|57.0_1|57.0_1|57.0_1|57.0_1|57.0_1|57.0_1|57.0_1|57.0_1|56.0_1|56.0_1|57.0_1|57.0_1|57.0_1|57.0_1|57.0_1|57.0_1|57.0_1|57.0_1|57.0_1|57.0_1|57.0_1|57.0_1|57.0_1|57.0_1|57.0_1|57.0_1|58.0_1|58.0_1|58.0_1|59.0_1|60.0_1|60.0_1|60.0_1|60.0_1|59.0_1|60.0_1|60.0_1|62.0_1|62.0_1|62.0_1|62.0_1|62.0_1|62.0_1|62.0_1|62.0_1|62.0_1|62.0_1|62.0_1|62.0_1|62.0_1|62.0_1|62.0_1|62.0_1|62.0_1|62.0_1|62.0_1|62.0_1|61.0_1|63.0_1|63.0_1|63.0_1|63.0_1|63.0_1|61.0_1|62.0_1|63.0_1|63.0_1|63.0_1|63.0_1|63.0_1|63.0_1|63.0_1|63.0_1|63.0_1|63.0_1|63.0_1|63.0_1|63.0_1|63.0_1|63.0_1|62.0_1|62.0_1|62.0_1|62.0_1|62.0_1|62.0_1|62.0_1|60.0_1|61.0_1|61.0_1|60.0_1|60.0_1|60.0_1|60.0_1|60.0_1|60.0_1|60.0_1|60.0_1|60.0_1|60.0_1|59.0_1|59.0_1|59.0_1|59.0_1|59.0_1|59.0_1|59.0_1|59.0_1|59.0_1|59.0_1|59.0_1|59.0_1|60.0_1|60.0_1|59.0_1|60.0_1|60.0_1|59.0_1|60.0_1|60.0_1|60.0_1|60.0_1|60.0_1|59.0_1|59.0_1|59.0_1|57.0_1|57.0_1|56.0_1|56.0_1|56.0_1|56.0_1|56.0_1|56.0_1|56.0_1|56.0_1|56.0_1|56.0_1|56.0_1|56.0_1|56.0_1|56.0_1|56.0_1|56.0_1|56.0_1|56.0_1|56.0_1|56.0_1|56.0_1|55.0_1|55.0_1|55.0_1|55.0_1|55.0_1|55.0_1|55.0_1|55.0_1|55.0_1|55.0_1|55.0_1|55.0_1|55.0_1|55.0_1|55.0_1|55.0_1|55.0_1|55.0_1|54.0_1|55.0_1|55.0_1|54.0_1|54.0_1|54.0_1|54.0_1|54.0_1|54.0_1|54.0_1|55.0_1|55.0_1|56.0_1|56.0_1|56.0_1|56.0_1|56.0_1|56.0_1|56.0_1|56.0_1|56.0_1|55.0_1|56.0_1|56.0_1|56.0_1|56.0_1|55.0_1|55.0_1|55.0_1|55.0_1|55.0_1|56.0_1|56.0_1|56.0_1|56.0_1|56.0_1|56.0_1|56.0_1|56.0_1|56.0_1|56.0_1|57.0_1|56.0_1|56.0_1|57.0_1|57.0_1|57.0_1|57.0_1|55.0_1|58.0_1|58.0_1|58.0_1|58.0_1|58.0_1|57.0_1|58.0_1|60.0_1|60.0_1|60.0_1|60.0_1|60.0_1|60.0_1|59.0_1|59.0_1|59.0_1|58.0_1|59.0_1|58.0_1|61.0_1|60.0_1|60.0_1|56.0_1|55.0_1|62.0_1|49.0_1";
	/** 均速持续距离（米）,超过这个距离的作为一类 **/
	int uniformSpeedContinueLength = 10;

	/** 均速波动误差±5kmph **/
	int uniformSpeedRrror = 5;

	/** 均速归类误差系数 **/
	float errorRatio = (float) 0.1;
	ArrayList<String> ss=new LaneSpeedSplitCombine().getClassPattern(line, uniformSpeedContinueLength, uniformSpeedRrror, errorRatio);
	
}
}
